
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { getAccounts, getTransactions, getCategories, createTransaction, updateTransaction, deleteTransaction } from './services/api';
import * as mockApi from './services/mockData';
import { ACTIVE_ENV } from './config'; // 导入环境配置
import type { AccountRead, TransactionRead, CategoryRead, TransactionStore, TransactionSplit } from './types';
import Header from './components/Header';
import AccountList from './components/AccountList';
import TransactionList from './components/TransactionList';
import BottomNav from './components/BottomNav';
import CreateTransactionModal from './components/CreateTransactionModal';
import TransactionDetailModal from './components/TransactionDetailModal';
import StatsView from './components/StatsView';
import Spinner from './components/ui/Spinner';
import TodaysSpending from './components/TodaysSpending';

const NetworkErrorDisplay = ({ onRetry }: { onRetry: () => void }) => (
    <div className="text-left p-6 bg-slate-800/50 rounded-2xl mx-4 mt-4 border border-red-500/50">
        <h3 className="text-xl font-bold text-red-300 mb-3">连接错误</h3>
        <p className="text-sm text-slate-300 mb-4">
            应用无法连接到您的 Firefly III 服务器。这通常由以下两个问题之一引起：
        </p>

        <div className="space-y-4 text-sm text-slate-400">
            <div>
                <strong className="font-semibold text-slate-200">1. 服务器离线:</strong>
                <p className="mt-1 pl-2">
                    位于 <code className="text-xs bg-slate-900 px-1 py-0.5 rounded">/api/v1</code> (通过您的代理) 的服务器未运行或无法访问。
                </p>
            </div>
            <div>
                <strong className="font-semibold text-slate-200">2. 浏览器安全策略 (CORS):</strong>
                <p className="mt-1 pl-2">
                    如果您未使用反向代理，您的 Firefly III 服务器需要配置为允许来自此网页应用的请求。请更新您 Firefly III 配置中的 <code className="text-xs bg-slate-900 px-1 py-0.5 rounded">CORS_ALLOWED_ORIGINS</code> 设置。
                </p>
            </div>
        </div>

        <button onClick={onRetry} className="mt-6 w-full px-5 py-3 bg-cyan-600 rounded-lg hover:bg-cyan-500 transition-colors text-white font-bold">
            重试连接
        </button>
    </div>
);

function App() {
    const [currentView, setCurrentView] = useState<'home' | 'stats'>('home');
    const [isModalOpen, setIsModalOpen] = useState(false);
    const [selectedTransaction, setSelectedTransaction] = useState<TransactionRead | null>(null);
    const [transactionToEdit, setTransactionToEdit] = useState<TransactionRead | null>(null);

    const [accounts, setAccounts] = useState<AccountRead[]>([]);
    const [transactions, setTransactions] = useState<TransactionRead[]>([]);
    const [categories, setCategories] = useState<CategoryRead[]>([]);

    const [loading, setLoading] = useState(true);
    const [error, setError] = useState<string | null>(null);
    const [isNetworkError, setIsNetworkError] = useState(false);

    const fetchData = useCallback(async (isRefreshing = false) => {
        if (!isRefreshing) setLoading(true);
        setError(null);
        setIsNetworkError(false);

        try {
            if (ACTIVE_ENV === 'mock') {
                await new Promise(res => setTimeout(res, 500)); // Simulate network delay
                const sortedTransactions = [...mockApi.mockTransactions].sort((a, b) =>
                    new Date(b.attributes.transactions[0].date).getTime() -
                    new Date(a.attributes.transactions[0].date).getTime()
                );
                setAccounts([...mockApi.mockAccounts]);
                setTransactions(sortedTransactions);
                setCategories([...mockApi.mockCategories]);
            } else {
                const [accRes, txRes, catRes] = await Promise.all([
                    getAccounts(),
                    getTransactions(),
                    getCategories(),
                ]);
                setAccounts(accRes.data);
                const sortedTransactions = txRes.data.sort((a, b) =>
                    new Date(b.attributes.transactions[0].date).getTime() -
                    new Date(a.attributes.transactions[0].date).getTime()
                );
                setTransactions(sortedTransactions);
                setCategories(catRes.data);
            }
        } catch (e) {
            if (e instanceof Error) {
                const lowerCaseMessage = e.message.toLowerCase();
                if (lowerCaseMessage.includes('failed to fetch')) {
                    setError('网络错误：无法连接到 API 服务器。这可能是 CORS 问题或服务器已离线。');
                    setIsNetworkError(true);
                } else if (lowerCaseMessage.includes('non iso-8859-1')) {
                    setError('API 令牌无效：API 令牌包含无效字符，无法使用。请验证该令牌。');
                    setIsNetworkError(false);
                } else {
                    setError(`发生意外错误： ${e.message}`);
                    setIsNetworkError(false);
                }
            } else {
                setError('发生未知错误。');
                setIsNetworkError(false);
            }
            console.error(e);
        } finally {
            setLoading(false);
        }
    }, []);

    useEffect(() => {
        fetchData();
    }, [fetchData]);

    const accountMap = useMemo(() => {
        return new Map(accounts.map(acc => [acc.id, acc]));
    }, [accounts]);

    const totalBalance = accounts.reduce((sum, acc) => sum + parseFloat(acc.attributes.current_balance), 0);
    const currencyCode = accounts.length > 0 ? accounts[0].attributes.currency_code : 'USD';

    const handleRefresh = () => {
        setLoading(true);
        fetchData(true).finally(() => setLoading(false));
    };

    const handleSaveTransaction = async (transactionData: TransactionStore, id?: string) => {
        if (ACTIVE_ENV === 'mock') {
            const split = transactionData.transactions[0];
            if (id) { // Editing
                const oldTx = transactions.find(t => t.id === id);
                if (!oldTx) return;
                const updatedTx: TransactionRead = {
                    ...oldTx,
                    attributes: {
                        ...oldTx.attributes,
                        group_title: split.description,
                        transactions: [{
                            ...oldTx.attributes.transactions[0],
                            type: split.type,
                            date: split.date,
                            amount: split.amount,
                            description: split.description,
                            source_id: split.source_id ?? null,
                            source_name: split.source_name ?? null,
                            destination_id: split.destination_id ?? null,
                            destination_name: split.destination_name ?? null,
                            category_name: split.category_name ?? null,
                            tags: split.tags ?? null,
                        }],
                    }
                };

                setTransactions(prev => prev.map(t => t.id === id ? updatedTx : t).sort((a, b) => new Date(b.attributes.transactions[0].date).getTime() - new Date(a.attributes.transactions[0].date).getTime()));
            } else { // Creating
                const newMockTransaction: TransactionRead = {
                    type: 'transactions',
                    id: `mock-tx-${Date.now()}`,
                    attributes: {
                        created_at: new Date().toISOString(),
                        updated_at: new Date().toISOString(),
                        group_title: split.description,
                        transactions: [{
                            type: split.type,
                            date: split.date,
                            amount: split.amount,
                            description: split.description,
                            source_id: split.source_id ?? null,
                            source_name: split.source_name ?? null,
                            destination_id: split.destination_id ?? null,
                            destination_name: split.destination_name ?? null,
                            category_id: `mock-cat-${Date.now()}`,
                            category_name: split.category_name ?? null,
                            tags: split.tags ?? null,
                        }],
                    },
                };
                setTransactions(prev => [newMockTransaction, ...prev].sort((a, b) => new Date(b.attributes.transactions[0].date).getTime() - new Date(a.attributes.transactions[0].date).getTime()));
            }
        } else {
            if (id) {
                await updateTransaction(id, transactionData);
            } else {
                await createTransaction(transactionData);
            }
            await fetchData(true);
        }
    };

    const handleDeleteTransaction = async (id: string) => {
        if (ACTIVE_ENV === 'mock') {
            setTransactions(prev => prev.filter(t => t.id !== id));
        } else {
            await deleteTransaction(id);
            await fetchData(true);
        }
        setSelectedTransaction(null);
    };

    const handleOpenEditModal = (tx: TransactionRead) => {
        setTransactionToEdit(tx);
        setSelectedTransaction(null);
        setIsModalOpen(true);
    };

    const handleCloseModal = () => {
        setIsModalOpen(false);
        setTransactionToEdit(null);
    };

    const renderContent = () => {
        if (loading && accounts.length === 0) {
            return <div className="flex justify-center items-center h-full pt-20"><Spinner /></div>;
        }
        if (error) {
            if(isNetworkError) {
                return <NetworkErrorDisplay onRetry={() => fetchData()} />;
            }
            return (
                <div className="text-center p-6 bg-slate-800/50 rounded-2xl mx-4 mt-4 border border-red-500/50">
                    <h3 className="text-lg font-semibold text-red-300">发生错误</h3>
                    <p className="mt-2 text-sm text-slate-300 text-left">{error}</p>
                    <button onClick={() => fetchData()} className="mt-6 px-5 py-2 bg-cyan-600 rounded-lg hover:bg-cyan-500 transition-colors text-white font-semibold">
                        重试
                    </button>
                </div>
            );
        }
        if (currentView === 'home') {
            return (
                <>
                    <AccountList accounts={accounts} />
                    <TodaysSpending transactions={transactions} currencyCode={currencyCode} />
                    <TransactionList
                        transactions={transactions}
                        onTransactionClick={setSelectedTransaction}
                        accountMap={accountMap}
                    />
                </>
            );
        }
        if (currentView === 'stats') {
            return <StatsView transactions={transactions} currencyCode={currencyCode} />;
        }
    };

    return (
        <div className="min-h-screen bg-slate-900 text-slate-100 flex justify-center">
            <div className="w-full max-w-md bg-slate-900 flex flex-col relative">
                <Header
                    totalBalance={totalBalance}
                    onRefresh={handleRefresh}
                    currencyCode={currencyCode}
                />
                <main className="flex-grow overflow-y-auto pb-24 px-4 space-y-6">
                    {renderContent()}
                </main>
                <BottomNav
                    currentView={currentView}
                    onViewChange={setCurrentView}
                    onAddClick={() => setIsModalOpen(true)}
                />
                <CreateTransactionModal
                    isOpen={isModalOpen}
                    onClose={handleCloseModal}
                    accounts={accounts}
                    categories={categories}
                    onSave={handleSaveTransaction}
                    transactionToEdit={transactionToEdit}
                />
                <TransactionDetailModal
                    transaction={selectedTransaction}
                    onClose={() => setSelectedTransaction(null)}
                    onEdit={handleOpenEditModal}
                    onDelete={handleDeleteTransaction}
                    accountMap={accountMap}
                />
            </div>
        </div>
    );
}

export default App;
